/**
 * Copyright (c) 2011 James Wendel
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package nlworks.wowapi;

import java.io.IOException;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import nlworks.wowapi.model.CharacterModel;
import nlworks.wowapi.params.ArenaRankingParams;
import nlworks.wowapi.params.ArenaTeamParams;
import nlworks.wowapi.params.AuctionParams;
import nlworks.wowapi.params.CharacterParams;
import nlworks.wowapi.params.GuildParams;
import nlworks.wowapi.params.RealmStatusParams;
import nlworks.wowapi.util.ConnectionManager;

public class WowAPI {

	private RegionLocale regionLocale;
	private String appKey;
	private String privateKey;
	private String baseURL;
	private String baseQuery;
	private ConnectionManager connectionManager;
	
	public enum RegionLocale {
		/** Region: North America <br> Language: English (en_US) */
		NORTH_AMERICA_en_US("us.battle.net", "en_US"),
		/** Region: North America <br> Language: Spanish (es_MX) */
		NORTH_AMERICA_es_MX("us.battle.net", "es_MX"),
		/** Region: Europe <br> Language: English (en_GB) */
		EUROPE_en_GB("eu.battle.net", "en_GB"),
		/** Region: Europe <br> Language: Spanish (es_ES) */
		EUROPE_es_ES("eu.battle.net", "es_ES"),
		/** Region: Europe <br> Language: French (fr_FR) */
		EUROPE_fr_FR("eu.battle.net", "fr_FR"),
		/** Region: Europe <br> Language: Russian (ru_RU) */
		EUROPE_ru_RU("eu.battle.net", "ru_RU"),
		/** Region: Europe <br> Language: German (de_DE) */
		EUROPE_de_DE("eu.battle.net", "de_DE"),
		/** Region: Korea <br> Language: Korean (ko_KR) */
		KOREA_ko_KR("kr.battle.net", "ko_KR"),
		/** Region: Taiwan <br> Language: Chinese (zh_TW) */
		TAIWAN_zh_TW("tw.battle.net", "zh_TW"),
		/** Region: China <br> Language: Chinese (zh_CN) */
		CHINA_zh_CN("battlenet.com.cn", "zh_CN");
		
		final private String server;
		final private String locale;

		private RegionLocale(String server, String locale) {
			this.server = server;
			this.locale = locale;
		}
	}
	
	public WowAPI(RegionLocale regionLocale) {
		this(regionLocale, null, null);
	}
	
	public WowAPI(RegionLocale regionLocale, String appKey, String privateKey) {
		this.appKey = appKey;
		this.privateKey = privateKey;
		this.regionLocale = regionLocale;
		
		if (appKey != null && privateKey != null) {
			baseURL = "https://" + regionLocale.server;
		} else {
			baseURL = "http://" + regionLocale.server;
		}
		
		baseQuery = "?locale=" + regionLocale.locale;
		connectionManager = new ConnectionManager();
	}
	
	public CharacterModel getCharacter(CharacterParams charParams) {
		StringBuilder sb = new StringBuilder(baseURL);
		charParams.toString(sb, baseQuery);
		String data = connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);

		return deserialize(data, CharacterModel.class);
	}
	
	public String getGuild(GuildParams guildParams) {
		StringBuilder sb = new StringBuilder(baseURL);
		guildParams.toString(sb, baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	public String getRealmStatus(RealmStatusParams realmStatusParams) {
		StringBuilder sb = new StringBuilder(baseURL);
		realmStatusParams.toString(sb, baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	public String getAuctions(AuctionParams auctionParams) {
		StringBuilder sb = new StringBuilder(baseURL);
		auctionParams.toString(sb, baseQuery);
		String data = connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
		///////////////////////////////////
		// TODO: a list of files will be returned that we need to fetch, process, and return
		///////////////////////////////////
		return data;
	}
	
	public String getArenaTeam(ArenaTeamParams arenaTeamParams) {
		StringBuilder sb = new StringBuilder(baseURL);
		arenaTeamParams.toString(sb, baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	public String getArenaRankings(ArenaRankingParams arenaRankingParams) {
		StringBuilder sb = new StringBuilder(baseURL);
		arenaRankingParams.toString(sb, baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	public String getItem(int itemId) {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/item/").append(itemId).append(baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}

	public String getRecipe(int recipeId) {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/recipe/").append(recipeId).append(baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}

	public String getQuest(int questId) {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/quest/").append(questId).append(baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	// ///////////////////////////////////////////////////////////////
	// methods with no parameters and always returns the same data
	// ///////////////////////////////////////////////////////////////
		
	public String getCharacterRaces() {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/data/character/races").append(baseQuery);
		String data = connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
		ObjectMapper mapper = new ObjectMapper();
		
		return null;
	}
	
	public String getCharacterClasses() {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/data/character/classes").append(baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	public String getGuildRewards() {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/data/guild/rewards").append(baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	public String getGuildPerks() {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/data/guild/perks").append(baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	public String getItemClasses() {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/data/item/classes").append(baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	public String getCharacterAchievements() {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/data/character/achievements").append(baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	public String getGuildAchievements() {
		StringBuilder sb = new StringBuilder(baseURL);
		sb.append("/api/wow/data/guild/achievements").append(baseQuery);
		return connectionManager.sendRequest(sb.toString(), 0, appKey, privateKey);
	}
	
	private <T> T deserialize(String data, Class<T> clazz) {
		
		ObjectMapper mapper = new ObjectMapper();
		try {
			return mapper.readValue(data, clazz);
		} catch (JsonParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonMappingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
}
